const config = require('./config')
const fs = require('fs')
// const async = require('async')

// 移除storage里面所有数据
function removeAllStorage (page) {
    return new Promise(async (resolve, reject) => {
        await page.evaluate(() => {
            window.localStorage.clear()
            window.sessionStorage.clear()
        }, {})
        resolve(true)
    })
}

function getStorage (page,localOrSession, key) {
    return new Promise(async (resolve, reject) => {
        const value = await page.evaluate((obj) => {
            const value = window[obj.localOrSession].getItem(`${obj.key}`)
            return value
        }, {localOrSession, key})
        resolve(value)
    })
}

// 获取指定class元素的页面位置
function getElementPosition (page, className) {
    return new Promise(async (resolve, reject) => {
        const element = await page.$(className)
        const size = await element.boundingBox()
        resolve(size)
    })
}

// 上传文件 上传文件一次最多能选择5个文件
function uploadFile (page) {
    return new Promise(async (resolve, reject) => {
        const fileList = fs.readdirSync(config.uploadDirPath)
        for (let item of fileList) {
            if (!item.startsWith('.')) {
                await uploadOneFile(page, `${config.uploadDirPath}/${item}`)
            }
        }
        resolve(true)
    })
}

function uploadOneFile (page, filePath) {
    return new Promise(async (resolve, reject) => {
        await selectAndClick(page, '.el-dialog .oss-upload')
        console.log('clicked upload')
        const uploadInput = await page.waitForSelector('.el-dialog .oss-upload #oss-file-upload');
        // 禁止浏览器文件选择框弹出
        // await page.evaluate(() => {
        //     const el = document.querySelector('.el-dialog #oss-file-upload')
        //     el.addEventListener('click', e => {
        //         e.preventDefault()
        //     })
        // }, {})
        await uploadInput.uploadFile(filePath);
        const uploadRes = await getRequestBody(page, `${config.env === 'prod' ? 'https' : 'http'}://${config.env}.ykt100.com/api/file/file/upload`)
        if (uploadRes.code === 0) {
            await clickByText(page, '.el-dialog .reserve-course-uplaod button span', '确认上传')
            await page.waitForTimeout(3000)
            resolve(true)
        } else {
            console.error('上传失败')
            reject('上传失败')
        }
    })
}
// 获取某个链接的body
function getRequestBody (page, url, pre) {
    return new Promise(async (resolve, reject) => {
        await page.on('response', async (res) => {
            if (pre) {
                if (res.url().startsWith(url)) {
                    const text = await res.text()
                    resolve(JSON.parse(text))
                }
            } else {
                if (res.url() === url) {
                    const text = await res.text()
                    resolve(JSON.parse(text))
                }
            }
        })
    })
}

function selectDate (page, date) {
    return new Promise(async (resolve, reject) => {
        // 需要从页面上获取年份
        await page.waitForTimeout(500)
        const picker = await page.$(".el-date-picker:last-of-type")
        let pageYear = await picker.$eval('.el-date-picker__header .el-date-picker__header-label:first-of-type', el => el.innerText)
        let pageMonth = await picker.$eval('.el-date-picker__header .el-date-picker__header-label:last-of-type', el => el.innerText)
        pageYear = pageYear.replace(/年/, '').trim() * 1
        pageMonth = pageMonth.replace(/月/, '').trim() * 1
        console.log('pageYear:', pageYear)
        console.log('pageMonth:', pageMonth)
        const arrDate = date.split('-')
        const resultYear = arrDate[0] * 1
        const resultMonth = arrDate[1] * 1
        const resultDay = arrDate[2] * 1

        console.log('resultYear:', resultYear)
        console.log('resultMonth:', resultMonth)
        console.log('resultDay:', resultDay)

        // 调节年份
        if (resultYear > pageYear) {
            const diff = resultYear - pageYear
            for (let i = 0; i < diff; i++) {
                const el = await page.$('.el-date-picker:last-of-type button[aria-label=后一年]')
                await el.click()
                await page.waitForTimeout(700)
            }
        } else if (resultYear < pageYear) {
            const diff = pageYear - resultYear
            for (let i = 0; i < diff; i++) {
                const el = await page.$('.el-date-picker:last-of-type button[aria-label=前一年]')
                await el.click()
                await page.waitForTimeout(700)
            }
        }

        // 调节月份
        if (resultMonth > pageMonth) {
            let monthDiff = resultMonth - pageMonth
            for (let i = 0; i < monthDiff; i++) {
                const el = await page.$('.el-date-picker:last-of-type button[aria-label=下个月]')
                await el.click()
                await page.waitForTimeout(700)
            }
        } else if (resultMonth < pageMonth) {
            let monthDiff = pageMonth - resultMonth
            for (let i = 0; i < monthDiff; i++) {
                const el = await page.$('.el-date-picker:last-of-type button[aria-label=上个月]')
                await el.click()
                await page.waitForTimeout(700)
            }
        }

        await clickByText(page, '.el-date-picker:last-of-type .available span', resultDay)
        resolve(true)
    })
}
// 获取课程开始时间
function getStartTime (delay) {
    const now = Date.now()
    const startTimeStamp = now + delay * 60 * 1000
    const startTime = new Date(startTimeStamp)
    const hour = startTime.getHours() > 9 ? startTime.getHours() : '0' + startTime.getHours()
    const minute = startTime.getMinutes() > 9 ? startTime.getMinutes() : '0' + startTime.getMinutes()
    console.log('start time:', hour, ' ', minute)
    return `${hour}:${minute}`
}

function xPathAndClick (page, xpath) {
    return new Promise(async (resolve, reject) => {
        const el = (await page.$x(xpath))[0];
        await el.click()
        resolve(true)
    })
}
/*
 * 获取元素的css样式
 * 注：需要使用完整的class路径： eg：.el-dialog:nth-last-of-type .el-dialog__footer button:nth-of-type(1) span
*/
function getElementStyle (page, elementClass) {
    return new Promise(async (resolve, reject) => {
        const style = await page.evaluate((elementClass) => {
            const el = document.querySelector(elementClass)
            if (!el) {
                console.log(`未找到elementClass为：${elementClass}的元素`)
                return
            }
            const elementStyle = window.getComputedStyle(el)
            return Promise.resolve(elementStyle)
        }, elementClass)
        resolve(style)
    })
}

/*
 * 作用：检查元素是否显示
 * 返回： 1：显示    0：不显示
*/
function checkElementIsDisplay (page, elementClass) {
    return new Promise(async (resolve, reject) => {
        const elementStyle = await getElementStyle(page, elementClass)
        if (!elementStyle) {
            console.log(`checkElementIsDisplay: 未找到指定class：${elementClass}的元素`)
            reject(`checkElementIsDisplay: 未找到指定class：${elementClass}的元素`)
        } else {
            const value = elementStyle.display === 'none' ? 0 : 1
            resolve(value)
        }
    })
}

// 重写input的值
function resetInputValue (page, inputClass) {
    console.log('开始清空input')
    return new Promise(async (resolve, reject) => {
        const input = await page.$(inputClass)
        if (input) {
            const inputDisplay = await checkElementIsDisplay(page, inputClass)
            if (!inputDisplay) {
                console.log(`当前inputClass：${inputClass}的display未none，无法进行设置`)
                reject(`当前inputClass：${inputClass}的display未none，无法进行设置`)
            } else {
                const result = await page.evaluate((inputClass) => {
                    const inputElement = document.querySelector(inputClass)
                    inputElement.value = ''
                    return Promise.resolve(true)
                }, inputClass)
                if (result) resolve(true)
            }
        } else {
            console.log(`resetInputValue: 未找到inputClass:${inputClass}`)
            reject(`resetInputValue: 未找到inputClass:${inputClass}`)
        }
    })
}

/*
 * 注意事项1：这里的className必须要准确
 * 注意事项2：这里使用的是innerHTML和text在比较，如果有空格啥的可能会获取不到元素
*/
function clickByText (page, className, text) {
    if (text && Number.isFinite(text)) {
        text += ''
    }
    console.log('will click text:', text)
    return new Promise(async (resolve, reject) => {
        const values = await page.$$eval(className, el => el.map(el => el.innerText))
        // console.log('values:', values)
        const els = await page.$$(className)
        if (values.length) {
            for(let i = 0; i < values.length; i++) {
                if (values[i] == text) {
                    console.log('找到了指定的text：', text)
                    await els[i].click()
                    resolve(true)
                    return
                }
                // console.log('text:', values[i])
                // if (values[i].trim() === text.trim()) {
                //     await els[i].click()
                //     // console.log('click text:', text)
                //     resolve(true)
                //     return
                // }
            }
            reject('没有找到指定text为：', text, '的元素')
        } else {
            console.log('没有筛选到元素 text:', text)
            reject('没有筛选到元素 text:' + text)
        }
    })
}

// 选择第index元素，并且调用type方法
function selectByIndexAndType (page, className, index) {
    return new Promise(async (resolve, reject) => {
        const els = await page.$$(className)
        if (index > els.length) {
            console.log('你输入的index大于元素个数')
            reject('你输入的index大于元素个数')
        } else {
            await els[index - 1].type('')
            resolve(true)
        }
    })
}

// 常用于日期之类的选择,如果value有值，则对输入框进行输入
function selectAndType (page, className, value = '') {
    return new Promise(async (resolve, reject) => {
        const _input = await page.$(className)
        if (_input) {
            await _input.type(value)
            resolve(true)
        } else {
            console.log(`未找到className为：${className}的input`)
            reject(`未找到className为：${className}的input`)
        }
    })
}

// 选择默认的时间
function selectDefaultDate(page) {
    return new Promise(async (resolve, reject) => {
        await page.waitForTimeout(400)
        const picker = await page.$(".el-date-picker:last-of-type")
        if (picker) {
            const today = await page.$('.el-date-picker:last-of-type .available.today')
            const defaultDate = await page.$('.el-date-picker:last-of-type .available.default')
            // console.log('today:', today)
            if (defaultDate) {
                console.log("currentPicker.$('.available.today')")
                await selectAndClick(page, '.el-date-picker:last-of-type .available.today')
                resolve(true)
            } else if (today) {
                console.log("picker.$('.available.today')")
                await selectAndClick(page, '.el-date-picker:last-of-type .available.today')
                resolve(true)
            } else {
                console.log('default 和 today 都没有')
                reject('default 和 today 都没有')
            }
        } else {
            console.log('当前没有date-picker')
            reject('当前没有date-picker')
        }
    })
}

// 选取input框并输入
function selectInputAddEdit (page, inputClass, value) {
    return new Promise(async (resolve, reject) => {
        try {
            const input = await page.$(inputClass)
            await input.type(value)
            resolve(true)
        } catch(err) {
            console.log(`selectInputAddEdit err: inputClass: ${inputClass}, value: ${value}`)
            reject(err)
        }
       
    })
}

// 点击相应的input，并选择最后一个select item
function selectFirstItem (page, inputClassName, index) {
    return new Promise(async (resolve, reject) => {
        const el = await page.$(inputClassName)
        await el.click()

        await page.waitForTimeout(300)
        const selectEl = await getLastSelectDropdown(page)
        if (selectEl) {
            if (index) {
                const _el = await selectEl.$(`.el-select-dropdown__item:nth-of-type(${index})`)
                await _el.click()
            } else {
                const _el = await selectEl.$('.el-select-dropdown__item:first-of-type')
                await _el.click()
            }
            resolve(true)
        } else {
            console.log('selectFirstItem：当前没有下拉选框')
            reject('selectFirstItem：当前没有下拉选框')
        }
    })
}

function clickFirstSelectDropdownItem (page) {
    return new Promise(async (resolve, reject) => {
        const selectEl = await getLastSelectDropdown(page)
        if (selectEl) {
            const _el = await selectEl.$('.el-select-dropdown__item:first-of-type')
            await _el.click()
            resolve(true)
        } else {
            console.log('clickFirstSelectDropdownItem：当前没有下拉选框')
            reject('clickFirstSelectDropdownItem：当前没有下拉选框')
        }
    })
}

// 选择display != none的下拉框
function getLastSelectDropdown (page) {
    return new Promise(async (resolve, reject) => {
        const dropdownSelect = await page.$$(".el-select-dropdown")
        if (dropdownSelect.length) {
            resolve(dropdownSelect[dropdownSelect.length - 1])
        } else {
            reject('getLastSelectDropdown: 当前没有下拉选框')
        }
    })
}

function getLastDialog (page) {
    return new Promise(async (resolve, reject) => {
        const dialogs = await page.$$(".el-dialog")
        if (dialogs.length) {
            resolve(dialogs[dialogs.length - 1])
        } else {
            reject('当前没有dialog')
        }
    })
}

function checkHasDisplay (obj) {
    for(let key in obj) {
        if (obj[key] === 'display') {
            return true
        }
    }
    return false
}

function selectAndClick (page, className) {
    return new Promise(async (resolve, reject) => {
        const el = await page.$(className)
        if (el) {
            await el.click()
            console.log(`click className: ${className}`)
            resolve(true)
        } else {
            reject(`selectAndClick err: ${className}`)
        }
    })
}

// 根据text选择元素
async function selectByText (page, text, className, tagName) {
    await page.evaluate((obj) => {
        let els
        if (obj.className && obj.tagName) {
            els = document.querySelectorAll(`.${obj.className} ${obj.tagName}`)
        } else if (obj.className){
            els = document.querySelectorAll(`.${obj.className}`)
        } else if (obj.tagName) {
            els = document.querySelectorAll(`${obj.tagName}`)
        }
        for (let i = 0; i < els.length; i++) {
            if (els[i].innerHTML === obj.text) return els[i]
        }
    }, {
        text, className, tagName
    })
}

// 点击dialog的header
function clickDialogHeader (lastDialog) {
    return new Promise(async (resove, reject) => {
        const el = await lastDialog.$('.el-dialog__header')
        if (el) {
            await el.click()
            resove(true)
        } else {
            reject('这个dialog没有header')
        }
    })
}

module.exports = {
    getStorage,
    getElementStyle,
    selectByText,
    selectAndClick,
    getLastDialog,
    checkHasDisplay,
    selectInputAddEdit,
    clickByText,
    getLastSelectDropdown,
    resetInputValue,
    checkElementIsDisplay,
    selectByIndexAndType,
    selectAndType,
    selectDefaultDate,
    selectFirstItem,
    xPathAndClick,
    clickDialogHeader,
    getStartTime,
    clickFirstSelectDropdownItem,
    selectDate,
    getRequestBody,
    uploadFile,
    getElementPosition,
    removeAllStorage
}